﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;

using Game.Map;

namespace Game.Surface
{
    public abstract class AbstractField : UserControl
    {
        public static readonly DependencyProperty ScaleProperty = DependencyProperty.Register(
            "Scale", typeof(Double), typeof(AbstractField), new PropertyMetadata(0d, OnScaleChanged));

        static void OnScaleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var p = d as UIElement;
            Debug.Assert(p != null, "p != null");

            var g = new ScaleTransform();
            g.ScaleX = g.ScaleY = GetScale(p);
            g.CenterX = 83;
            g.CenterY = 50;
            p.RenderTransform = g;
        }

        public static double GetScale(UIElement element)
        {
            return (double)element.GetValue(ScaleProperty);
        }

        public static void SetScale(UIElement element, double value)
        {
            element.SetValue(ScaleProperty, value);
        }

        public readonly static double Size = 100;

        readonly IMapFieldView _mapField;
        readonly Collection<SurfaceFieldDecorator> _decorators = new Collection<SurfaceFieldDecorator>();
            
        protected AbstractField(IMapFieldView field)
        {
            _mapField = field;
            Width = 300;
            Height = 300;

            Clip = CreateGeometry(Size - 0.4);
            Background = Brushes.Transparent;
            //UpdateBitmap(field);
        }

        public Collection<SurfaceFieldDecorator> Decorators
        {
            get { return _decorators; }
        }

        public Brush Fill
        {
            get { return Background; }
            set { Background=value; }
        }
        
        protected virtual bool CanZoom()
        {
            return false;
        }

        public void Update()
        {
            Update(false);
        }
        
        public void Update(bool force)
        {
            UpdateBitmap(_mapField, force);
        }

        public IMapFieldView MapField
        {
            get { return _mapField; }
        }

        public double Top
        {
            get
            {
                double top = (_mapField.Point.Y * Size);

                bool even = ((_mapField.Point.X % 2) == 0);
                if (even)
                {
                    top += (0.5 * Size);
                }

                return top;
            }
        }

        public double Left
        {
            get { return (_mapField.Point.X * Size); }
        }

        protected virtual void UpdateBitmap(IMapFieldView field)
        {
            UpdateBitmap(field, false);
        }
        
        protected abstract void UpdateBitmap(IMapFieldView field, bool force);

        PathGeometry CreateGeometry(double width)
        {
            var geometry = new PathGeometry();
            var figure = new PathFigure {IsFilled = true};

            var points = GetPoints(width);
            figure.StartPoint = new Point(points[0].X, points[0].Y);
            for(int i = 1; i < points.Count; i++)
            {
                var p = points[i];
                var segment = new LineSegment {Point = p};
                figure.Segments.Add(segment);
            }

            figure.IsClosed = true;
            geometry.Figures.Add(figure);

             return geometry;
        }
        
        protected List<Point> GetPoints(double width)
        {
            List<Point> result = new List<Point>();
            var size = new Size(width, width);
            var points = Common.GameHexagon.GetPolygonPoints(size);
            foreach(var p in points)
            {
                result.Add(new Point(p.X + 33, p.Y));
            }
            
            return result;
        }

    }
}
